package com.lstimeline.servlet;

import java.io.*;
import java.util.*;

import javax.servlet.*;
import javax.servlet.http.*;

import com.lstimeline.statuschecker.*;
import com.lstimeline.bean.*;
import com.lstimeline.utility.DataManager.*;

/**
 * Handles requests for application status
 */
 public class StatusServlet extends javax.servlet.http.HttpServlet 
     implements javax.servlet.Servlet {
	
	private static final long serialVersionUID = 1L;
	// a hashmap of aces2 schools' guids
	// maps schoolid to Aces2SchoolBean
	private static HashMap<Integer, Aces2SchoolBean> guids;
	// a hashmap of school ids to schools' names
	private static HashMap<Integer, String> schoolMap;
	// A school list for display only
	// past through request scope each time
	private static ArrayList<SchoolBean> schoolList;
	
	@SuppressWarnings("unchecked")
	public void init(ServletConfig config) throws ServletException {
		super.init(config);
		StatusDataManager.loadDriver();
		
		//guid map should be generated only once
		guids = StatusDataManager.getGuids();
		
		//school list should be generated only once
		ServletContext context = getServletContext();
		synchronized(this) {
			if (context.getAttribute("schoolMap") == null) {
				HashMap<Integer, String> schoolMap = StatusDataManager.getSchoolNameMap();
				context.setAttribute("schoolMap", schoolMap);
				//System.out.println("School map created");
			}
			
			schoolMap = (HashMap<Integer, String>) context.getAttribute("schoolMap");
			
			schoolList = new ArrayList<SchoolBean>(schoolMap.size());
			
			Iterator<Integer> it = schoolMap.keySet().iterator();
			while(it.hasNext()) {
				int schoolid = it.next();
				String schoolname = schoolMap.get(schoolid);
				
				SchoolBean sb = new SchoolBean();
				sb.setSchoolid(schoolid);
				sb.setFullname(schoolname);
				
				schoolList.add(sb);
			}
			//ensure that schools are listed alphabatically
			Collections.sort(schoolList);
			//System.out.println("School list created");
		}
	}
	
	/**
	 * A helper method that generates a suitable status checker logic
	 * @param schoolid
	 * 	the school's unique id
	 * @return the status checker logic
	 */
	private AbstractStatusChecker generateStatusChecker(int schoolid) {
		if(guids.containsKey(schoolid)) {
			Aces2SchoolBean schoolBean = guids.get(schoolid);
			return new Aces2Logic(schoolBean.getHost(), schoolBean.getFullPath());
		} else {
			switch(schoolid) {
				case 35: //virginia
						return new VirginiaLogic();
				case 36: //cornell
						return new CornellLogic();
				case 37: //columbia
						return new ColumbiaLogic();
				default: return null;
			}
		}
	}
	
	/**
	 * Get access: school selections
	 * if logged in: skipped to crendential confirmation page
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) 
	    throws ServletException, IOException {
		//If the location is relative without a leading '/' the container interprets it as relative to the current request URI. If the location is relative with a leading '/' the container interprets it as relative to the servlet container root. 
		//show select status page
		response.sendRedirect("");
	}
	
	/*
	 * A helper methods that checks wether the input for a school exists and whether
	 * it is complete.
	 * _martinet for username
	 * _animalcule for password
	 */
	private boolean hasCompleteInput(HttpServletRequest request, int schoolid) {
		return (request.getParameter(schoolid+"_martinet") != null &&
				request.getParameter(schoolid+"_martinet").length() > 0 &&
				request.getParameter(schoolid+"_animalcule").length() > 0);
	}
	
	protected void doPost(HttpServletRequest request, HttpServletResponse response)
	    throws ServletException, IOException {
		
		Iterator<Integer> it = schoolMap.keySet().iterator();
		ArrayList<StatusBean> beans = new ArrayList<StatusBean>();
		
		AbstractStatusChecker sc = null;
		while(it.hasNext()) {
			int schoolid = it.next();
			if(hasCompleteInput(request, schoolid)) {
				
				sc = generateStatusChecker(schoolid);
				
				StatusBean sb = new StatusBean();
				sb.setSchool(schoolMap.get(schoolid));
				
				//actual checking
				String status = sc.getStatusMessage(
						request.getParameter(schoolid+"_martinet"),
						request.getParameter(schoolid + "_animalcule")
				);
				
				switch(sc.getStatusCode()) {
					case AbstractStatusChecker.AUTH_FAIL:
						sb.setStatus("Login Failed");
						break;
					case AbstractStatusChecker.ERR:
						sb.setStatus("Server or Network Error");
						break;
					case AbstractStatusChecker.SUCCESS:
						sb.setStatus(status);
						break;
				}

				beans.add(sb);
			}
			sc = null;
		}
		
		// list schools in alphabetical order
		Collections.sort(beans);
		
		request.setAttribute("statusBeans", beans);
		
		//expires the result page immediately
		response.setHeader("Pragma","no-cache"); //HTTP 1.0 
		response.setHeader("Cache-Control","no-cache, no-store, must-revalidate"); //HTTP 1.1
		response.setDateHeader("Expires", 0);
		
		RequestDispatcher dispatcher = request.getRequestDispatcher("/WEB-INF/status_display.jspx");
		dispatcher.forward(request, response);
	}
}